﻿using System;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Activation;
using GraphInformation;
using QuickGraph;
using QuickGraph.Serialization;
using EpidemicSimulator;
using System.IO;
using System.Collections.Generic;
using System.Reflection;
using ComplexNetGeneratorLib;
using EpidemicSimulator.states;
using System.Web;
using System.Xml.Linq;
using ComplexNetCentralityLib;
using System.Net;
using System.Globalization;
using EpidemicSimulator.stopconditions;
using GraphMLComplexType;
using EpidemicSimulator.reports;
using EpidemicSimulator.strategies;
using QuickGraphBuilder;

namespace CARE.Web
{
    [ServiceContract(Namespace = "")]
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    public class GraphProviderService
    {
        db.DiseaseDataClassesDataContext DataContext = new db.DiseaseDataClassesDataContext();

        [OperationContract]
        public Graph GetDiseaseModelGraphByName(string DiseaseName)
        {
            var b = from x in DataContext.Diseases where x.name == DiseaseName select x;
            return GetDiseaseModelGraph(b.First().data.ToString());
        }

        [OperationContract]
        public Graph GetDiseaseModelGraph(string GraphML)
        {

            var g = new AdjacencyGraph<DiseaseModelNode, DiseaseModelEdge>();
            StringReader reader = new StringReader(GraphML);
            try
            {
                g.DeserializeFromGraphML(
                    reader,
                    id => new DiseaseModelNode(),
                    new IdentifiableEdgeFactory<DiseaseModelNode, DiseaseModelEdge>(SimulationFactory.CreateEdge<DiseaseModelNode, DiseaseModelEdge>)
                );
            }
            catch (Exception e)
            {
                throw e;
            }
            reader.Close();

            return GetGraphForSilverlight(g);
        }

        private static Graph GetGraphForSilverlight(QuickGraph.AdjacencyGraph<DiseaseModelNode, DiseaseModelEdge> g)
        {
            Graph resultG = new Graph() { ID = Guid.NewGuid() };
            var map = new Dictionary<DiseaseModelNode, GraphElement>();
            resultG.Vertices = new List<GraphElement>();
            //var list = new List<GraphElement>();
            for (int i = 0; i < g.VertexCount; i++)
            {
                var v = g.Vertices.ElementAt(i);
                var elem = new GraphElement();
                elem.ID = Guid.NewGuid();
                elem.GraphID = resultG.ID;
                elem.Keys = new List<PairKeyValue>();
                elem.Keys.Add(new PairKeyValue() { Key = "nodeColor", Value = v.nodeColor, ID = Guid.NewGuid(), ElementID = elem.ID });
                elem.Keys.Add(new PairKeyValue() { Key = "nodeX", Value = v.nodeX, ID = Guid.NewGuid(), ElementID = elem.ID });
                elem.Keys.Add(new PairKeyValue() { Key = "nodeY", Value = v.nodeY, ID = Guid.NewGuid(), ElementID = elem.ID });
                elem.Keys.Add(new PairKeyValue() { Key = "stateName", Value = v.stateName, ID = Guid.NewGuid(), ElementID = elem.ID });
                resultG.Vertices.Add(elem);
                map.Add(v, elem);
            }

            var list1 = new List<GraphEdge>();
            resultG.Edges = new List<GraphEdge>();
            for (int i = 0; i < g.Edges.Count(); i++)
            {
                var e = g.Edges.ElementAt(i);
                resultG.Edges.Add(new GraphEdge() { GraphID = resultG.ID, ID = Guid.NewGuid(), Source = map[e.Source].ID, Target = map[e.Target].ID, Condition = e.condition });
            }

            return resultG;
        }

        [OperationContract]
        public String GenerateGraphAndSaveGraphML(string methodName, string[] param, string[] paramTypes, int condition)
        {
            return CreateGraphMLFromGraph(GenerateGraph(methodName, param, paramTypes, condition));
        }

        [OperationContract]
        public List<String> GetDiseaseModelStateNames()
        {
            List<String> states = new List<string>();

            Type t = typeof(State);

            Assembly asm = t.Assembly;

            foreach (Type type in asm.GetTypes())
            {
                if (type.BaseType == t)
                {
                    String val = type.FullName;
                    states.Add(val);
                }
            }

            return states;
        }

        [OperationContract]
        public Graph GetGraphFromGraphML(String graphML)
        {
            Simulation s = null;
            SimulationSetup simsetup = new SimulationSetup(graphML, null, 1, 1);
            s = SimulationFactory.createSimulation(simsetup, HttpContext.Current.Server.MapPath(@"~/App_Data"));
            var resultGraph = s.getSimulationResultForSilverlight();
            return resultGraph;
            return new Graph();
        }

        [OperationContract]
        public Graph GenerateGraph(string methodName, string[] param, string[] paramTypes, int condition)
        {
            MethodInfo method = typeof(ComplexNetGeneratorLib.ComplexNetGenerator).GetMethod(methodName);
            ComplexNetGenerator generator = new ComplexNetGenerator();

            int j = 0;
            object[] paramObj = new object[param.Count()];
            for (int i = 0; i < param.Count(); i++)
            {
                switch (paramTypes[j++])
                {
                    case "System.Int32":
                        paramObj[i] = int.Parse(param[i]);
                        break;
                    case "System.Double":
                        paramObj[i] = double.Parse(param[i]);
                        break;
                    default:
                        break;
                }
            }

            ComplexNet net = method.Invoke(generator, paramObj) as ComplexNet;

            Graph graph = CreateGraphFromComplexNet(net);

            // TODO: dane osob z BD
            //DataBaseClassesDataContext db = new DataBaseClassesDataContext();
            //var nodes = from n in db.Nodes
            //            select n;
            //var nodesArray = nodes.ToArray();

            //Random random = new Random();
            //foreach (var vertex in graph.Vertices)
            //{
            //    var n = nodesArray[random.Next() % nodesArray.Length];

            //    vertex.Keys.Add(new PairKeyValue("birthdate", n.birthdate.ToString()));
            //    vertex.Keys.Add(new PairKeyValue("country", n.country));
            //    vertex.Keys.Add(new PairKeyValue("image", n.image.ToString()));//zmiana spowodowana innym sposobem przechowywania zdjec
            //    vertex.Keys.Add(new PairKeyValue("latitude", n.latitude.ToString()));
            //    vertex.Keys.Add(new PairKeyValue("longitude", n.longitude.ToString()));
            //    vertex.Keys.Add(new PairKeyValue("name", n.name));
            //    vertex.Keys.Add(new PairKeyValue("postalcode", n.postalcode));
            //    vertex.Keys.Add(new PairKeyValue("street", n.street));
            //    vertex.Keys.Add(new PairKeyValue("surname", n.surname));
            //    vertex.Keys.Add(new PairKeyValue("town", n.town));
            //}

            foreach (var edge in graph.Edges)
            {
                edge.Condition = condition;
            }


            return graph;
        }

        [OperationContract]
        public Graph StartSimulation(SimulationSetupSL simsetup, String token)
        {
            Graph resultG = new Graph();
            Simulation s = null;

            if (simsetup.networkGraph != null)
            {
                var graph = simsetup.networkGraph.GetGraphFormSilverlight();
            }

            SimulationSetup simulationSetup = new SimulationSetup(simsetup.networkGraphML, simsetup.diseaseModelGraphML, simsetup.maxContactsPerStep, simsetup.minContactsPerStep);
            simulationSetup.condition = simsetup.condition;
            simulationSetup.networkGraph = simsetup.networkGraph;
            simulationSetup.stateChangePlansSL = simsetup.stateChangePlansSL;
            simulationSetup.stopConditionsSL = simsetup.stopConditionsSL;
            s = SimulationFactory.createSimulation(simulationSetup, HttpContext.Current.Server.MapPath("App_Data"));

            HttpContext.Current.Session.Add("simulation", s);
            resultG = s.getSimulationResultForSilverlight();

            //Context.Session["simulation"] = s;
            //Application[token] = s;

            return resultG;
        }

        [OperationContract]
        public Graph CreateGraph(String graphML, String stateMachineGraphML, String token, int MaxSimStep)
        {
            Simulation s = null;
            SimulationSetup simsetup = new SimulationSetup(graphML, stateMachineGraphML, 1, 1);
            s = SimulationFactory.createSimulation(simsetup, HttpContext.Current.Server.MapPath("App_Data"));//HttpContext.Current.Server.MapPath("App_Data/terror.graphml.xml"), HttpContext.Current.Server.MapPath("App_Data/sis.graphml.xml"));
            s.addStopCondition(new MaxSimStepNumberStopCondition(MaxSimStep));
            return s.getSimulationResultForSilverlight();
        }

        [OperationContract]
        public Graph ComputeCentrality(String MethodName, Graph input)
        {
            UndirectedGraph<SocialNetworkNode, EdgeWithAttributes.EdgeWithAttributes<SocialNetworkNode>> graph = input.GetGraphFormSilverlight();
            AdjacencyGraph<IGraphMLComplexType, EdgeWithAttributes.EdgeWithAttributes<IGraphMLComplexType>> network = new AdjacencyGraph<IGraphMLComplexType, EdgeWithAttributes.EdgeWithAttributes<IGraphMLComplexType>>();
            foreach (EdgeWithAttributes.EdgeWithAttributes<SocialNetworkNode> edge in graph.Edges)
            {
                EdgeWithAttributes.EdgeWithAttributes<IGraphMLComplexType> e = new EdgeWithAttributes.EdgeWithAttributes<IGraphMLComplexType>(edge.Source, edge.Target);
                network.AddVerticesAndEdge(e);
            }

            Type complex = typeof(ComplexNetCentralityLib.ComplexNetCentrality);
            Graph centralityGraph = null;
            try
            {
                centralityGraph = (Graph)complex.GetMethod(MethodName).Invoke(null, new object[] { network });
                input.Merge(network);
            }
            catch (Exception e)
            {
                throw;
            }

            return input;
        }

        [OperationContract]
        public Graph NextStep(String token)
        {         
            Simulation s = HttpContext.Current.Session["simulation"] as Simulation;
            s.nextSimStep();
            HttpContext.Current.Session["simulation"] = s;
            
            Graph resultG;
            resultG = s.getSimulationResultForSilverlight();            
            resultG.Height = CountInfectious(s);
            return resultG;
        }

        [OperationContract]
        public List<String> GetAvailableMethodsOfGenerator()
        {
            MethodInfo[] methods = typeof(ComplexNetGeneratorLib.ComplexNetGenerator).GetMethods();
            List<String> toReturn = new List<string>();

            foreach (var item in methods)
                if (item.Name.StartsWith("generate"))
                    toReturn.Add(item.Name);

            return toReturn;
        }

        [OperationContract]
        public List<String> GetParametersFromMethod(string methodName)
        {
            MethodInfo method = typeof(ComplexNetGeneratorLib.ComplexNetGenerator).GetMethod(methodName);
            List<string> toReturn = new List<string>();

            ParameterInfo[] parameters = method.GetParameters();
            foreach (var p in parameters)
                toReturn.Add(p.Name);

            return toReturn;
        }

        [OperationContract]
        public List<String> GetParametersTypesFromMethod(string methodName)
        {
            MethodInfo method = typeof(ComplexNetGeneratorLib.ComplexNetGenerator).GetMethod(methodName);
            ParameterInfo[] parameters = method.GetParameters();
            List<string> types = new List<string>();
            foreach (var item in parameters)
                types.Add(item.ParameterType.ToString());

            return types;
        }

        [OperationContract]
        public List<String> GetAvailableStateChangeStrategies()
        {
            List<String> strategies = new List<string>();
            Type t = typeof(EpidemicSimulator.strategies.StateChangeStrategy);
            Assembly asm = t.Assembly;
            foreach (Type type in asm.GetTypes())
            {
                Type[] interfaces = type.GetInterfaces();
                foreach (Type interFace in interfaces)
                {

                    if (interFace.FullName == t.FullName)
                    {
                        String val = type.Name;
                        strategies.Add(val);
                    }
                }
            }
            return strategies;
        }

        [OperationContract]
        public List<String> GetAvailableMethodsOfCentrality()
        {
            MethodInfo[] methods = typeof(ComplexNetCentrality).GetMethods(BindingFlags.Static | BindingFlags.Public);
            List<String> toReturn = new List<string>();

            foreach (var item in methods)
            {
                ParameterInfo[] infos = item.GetParameters();
                if (infos.Count() == 1)
                {
                    if (infos[0].Name == "socialNetwork")
                        toReturn.Add(item.Name);
                }
            }

            return toReturn;
        }

        [OperationContract]
        public Double[] GetGeoCode(string strAddress)
        {
            string strKey = "ABQIAAAAt21w088otvkx4dydGkSFzhTiWYdC4kK5HJo75hRqCbZEyPurWxRFE2iDTU5WiKeD_zuNhg5zVaDZbw";

            string sPath = "http://maps.google.com/maps/geo?q=" + strAddress + "&output=csv&key=" + strKey;

            WebClient client = new WebClient();

            string[] eResult = client.DownloadString(sPath).ToString().Split(',');

            string latitude = eResult.GetValue(2).ToString();
            string longitude = eResult.GetValue(3).ToString();

            return new double[] { Convert.ToDouble(latitude, NumberFormatInfo.InvariantInfo), Convert.ToDouble(longitude, NumberFormatInfo.InvariantInfo) };
        }

        private String CreateGraphMLFromGraph(Graph g)
        {
            //int condition = 0;

            String siec = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + Environment.NewLine +
            "<graphml xmlns=\"http://graphml.graphdrawing.org/xmlns\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://graphml.graphdrawing.org/xmlns " +
            "http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd\">" + Environment.NewLine +
            "  <key id=\"id\" for=\"node\" attr.name=\"id\" attr.type=\"string\" />" + Environment.NewLine +
            "  <key id=\"name\" for=\"node\" attr.name=\"name\" attr.type=\"string\" />" + Environment.NewLine +
            "  <key id=\"surname\" for=\"node\" attr.name=\"surname\" attr.type=\"string\" />" + Environment.NewLine +
            "  <key id=\"birthdate\" for=\"node\" attr.name=\"birthdate\" attr.type=\"string\" />" + Environment.NewLine +
            "  <key id=\"photo\" for=\"node\" attr.name=\"photo\" attr.type=\"string\" />" + Environment.NewLine +
            "  <key id=\"location\" for=\"node\" attr.name=\"location\" attr.type=\"string\" />" + Environment.NewLine +
            "  <key id=\"locationX\" for=\"node\" attr.name=\"locationX\" attr.type=\"string\" />" + Environment.NewLine +
            "  <key id=\"locationY\" for=\"node\" attr.name=\"locationY\" attr.type=\"string\" />" + Environment.NewLine +
            "  <key id=\"street\" for=\"node\" attr.name=\"street\" attr.type=\"string\" />" + Environment.NewLine +
            "  <key id=\"town\" for=\"node\" attr.name=\"town\" attr.type=\"string\" />" + Environment.NewLine +
            "  <key id=\"postalcode\" for=\"node\" attr.name=\"postalcode\" attr.type=\"string\" />" + Environment.NewLine +
            "  <key id=\"country\" for=\"node\" attr.name=\"country\" attr.type=\"string\" />" + Environment.NewLine +
            "  <key id=\"stateName\" for=\"node\" attr.name=\"stateName\" attr.type=\"string\" />" + Environment.NewLine +
            " <graph edgedefault=\"undirected\">" + Environment.NewLine;

            int j = 1;
            String xmlNode;
            foreach (var node in g.Vertices)
            {
                xmlNode = "<node id=\"" + Convert.ToString(node.ID) + "\">" + Environment.NewLine;

                xmlNode +=
        "      <data key=\"id\">" + Convert.ToString(node.ID) + "</data>" + Environment.NewLine +
        "      <data key=\"name\">name" + j + "</data>" + Environment.NewLine +
        "      <data key=\"surname\">surname" + j + "</data>" + Environment.NewLine +
        "      <data key=\"birthdate\">" + DateTime.Now + "</data>" + Environment.NewLine +
        "      <data key=\"photo\">http://nosoifighters.studentlive.pl/GetImage.aspx?id=44</data>" + Environment.NewLine +
        "      <data key=\"location\">location" + j + "</data>" + Environment.NewLine +
        "      <data key=\"locationX\">0</data>" + Environment.NewLine +
        "      <data key=\"locationY\">0</data>" + Environment.NewLine +
        "      <data key=\"street\">street" + j + "</data>" + Environment.NewLine +
        "      <data key=\"town\">town" + j + "</data>" + Environment.NewLine +
        "      <data key=\"postalcode\"></data>" + Environment.NewLine +
        "      <data key=\"country\">country" + j + "</data>" + Environment.NewLine +
        "      <data key=\"stateName\">Susceptible</data>" + Environment.NewLine + "</node>" + Environment.NewLine;


                //TODO: jesli zostanie skonczony edytor
                //String key = "<data key=\"";
                //HashSet<String>.Enumerator e = node.attributes.GetEnumerator();
                //while (e.MoveNext())
                //{
                //    String attName = e.ToString();
                //    String att = e.Current;
                //}
                siec += xmlNode;

                j++;
            }

            String xmlEdge;
            int i = 0;
            foreach (var edge in g.Edges)
            {
                xmlEdge = "<edge id=\"" + (i++) + "\" source=\"" + edge.Source + "\" target=\"" + edge.Target + "\" condition=\"" + edge.Condition + "\" " + "/>" + Environment.NewLine;
                siec += xmlEdge;
            }

            siec += "  </graph>" + Environment.NewLine + "</graphml>";

            return siec;
        }

        private Graph CreateGraphFromComplexNet(ComplexNet net)
        {
            Graph g = new Graph();
            g.ID = Guid.NewGuid();
            Dictionary<ComplexNetNode, GraphElement> map = new Dictionary<ComplexNetNode, GraphElement>();
            int i = 0;
            g.Vertices = new List<GraphElement>();
            foreach (ComplexNetNode node in net.nodes)
            {
                GraphElement v = new GraphElement()
                {
                    ID = Guid.NewGuid(),
                    GraphID = g.ID,
                    Keys = new List<PairKeyValue>()
                };
                v.Keys.Add(new PairKeyValue()
                {
                    ID = Guid.NewGuid(),
                    Key = v.ID + "_Key",
                    Value = v.ID + "_Value"
                });
                map.Add(node, v);
                g.Vertices.Add(v);
            }

            i = 0;
            g.Edges = new List<GraphEdge>();
            foreach (ComplexNetEdge edge in net.edges)
            {
                GraphEdge e = new GraphEdge()
                {
                    ID = Guid.NewGuid(),
                    GraphID = g.ID,
                    Source = map[edge.source].ID,
                    Target = map[edge.target].ID
                };
                g.Edges.Add(e);
            }

            return g;
        }

        //OLD

        [OperationContract]
        public Graph CreateGraphFromGraphML(String graphML)
        {

            //string token="12";
            Simulation s = null;
            SimulationSetup simsetup = new SimulationSetup(graphML, null, 1, 1);
            s = SimulationFactory.createSimulation(simsetup, HttpContext.Current.Server.MapPath("App_Data"));//HttpContext.Current.Server.MapPath("App_Data/terror.graphml.xml"), HttpContext.Current.Server.MapPath("App_Data/sis.graphml.xml"));

            //Application[token.ToString()] = s;

            return s.getSimulationResultForSilverlight();
        }

        [OperationContract]
        public int getSimulationMaxTime()
        {
            Simulation s = HttpContext.Current.Session["simulation"] as Simulation;
            foreach (var c in s.stopConditions)
            {
                if (c is MaxSimStepNumberStopCondition)
                    return ((c as MaxSimStepNumberStopCondition)).getMaxSimTimeStepNumberStopCondition();
            }
            return int.MaxValue;
        }

        [OperationContract]
        public Graph CreateDiseaseModelGraph(string modelML)
        {
            Graph resultG = new Graph();

            var g = new AdjacencyGraph<DiseaseModelNode, DiseaseModelEdge>();
            StringReader reader = new StringReader(modelML);
            try
            {
                g.DeserializeFromGraphML(
                    reader,
                    id => new DiseaseModelNode(),
                    new IdentifiableEdgeFactory<DiseaseModelNode, DiseaseModelEdge>(SimulationFactory.CreateEdge<DiseaseModelNode, DiseaseModelEdge>)
                );
            }
            catch (Exception e)
            {
                throw e;
            }
            reader.Close();

            return GetGraphForSilverlight(g);
        }

        [OperationContract]
        public void StartSimulationInBackGround(SimulationSetupSL simsetup, int numOfExperiments)
        {
            SimulationSetup simulationSetup = new SimulationSetup(simsetup.networkGraphML, simsetup.diseaseModelGraphML, simsetup.maxContactsPerStep, simsetup.minContactsPerStep);
            simulationSetup.networkGraph = simsetup.networkGraph;
            simulationSetup.stateChangePlansSL = simsetup.stateChangePlansSL;
            simulationSetup.stopConditionsSL = simsetup.stopConditionsSL;

            SimulationManager simManager = new SimulationManager(simulationSetup, numOfExperiments, HttpContext.Current.Server.MapPath("App_Data"));
            simManager.runSimulationAsync();
            HttpContext.Current.Session["AsyncSimManager"] = simManager;
        }

        [OperationContract]
        public ExperimentState[] getExporimentState()
        {
            try
            {
                SimulationManager simManager = (SimulationManager)HttpContext.Current.Session["AsyncSimManager"];
                return simManager.getExperimentState();
            }
            catch (Exception e)
            { }

            return null;
        }

        [OperationContract]
        public SimulationSimpleReport getAsyncSimulationReport()
        {
            try
            {
                SimulationManager simManager = (SimulationManager)HttpContext.Current.Session["AsyncSimManager"];
                return simManager.getSimulationReport();
            }
            catch (Exception e)
            { }

            return null;
        }

        [OperationContract]
        public void AddStateChangePlan(StateChangePlanSL plan, String token)
        {
            Simulation s = null;

            if (HttpContext.Current.Application[token] != null)
            {
                s = (Simulation)HttpContext.Current.Application[token.ToString()];
            }

            StateChangePlan stateChangePlan = null;

            Type type = Type.GetType(plan.stateChangeStrategyName, true);
            object newInstance = Activator.CreateInstance(type);

            StateChangeStrategy strategy = (StateChangeStrategy)newInstance;
            if (plan.inPersents)
            {
                stateChangePlan = new PersentageStateChangePlan(plan.value, strategy, plan.applyTime);
            }
            else
            {
                stateChangePlan = new NumericalStateChangePlan(plan.value, strategy, plan.applyTime);
            }
            s.addStateChangePlan(stateChangePlan);
        }

        [OperationContract]
        public Graph CreateGraphWithDiseaseModelGraph(String graphML, DiseaseModelGraph stateMachineGraph, String token, int MaxSimStep)
        {
            Simulation s = null;

            //s = SimulationFactory.createSimulation(graphML, stateMachineGraphML, HttpContext.Current.Server.MapPath("App_Data"));//HttpContext.Current.Server.MapPath("App_Data/terror.graphml.xml"), HttpContext.Current.Server.MapPath("App_Data/sis.graphml.xml"));
            //s.addStopCondition(new MaxSimStepNumberStopCondition(MaxSimStep));
            //Application[token.ToString()] = s;

            //var g = s.getSimulationResultForSilverlight();

            HttpContext.Current.Application[token] = s;

            Graph resultG = new Graph();
            //resultG.Vertices = new GraphElement[g.VertexCount];
            //for (int i = 0; i < g.VertexCount; i++)
            //{
            //    var v = g.Vertices.ElementAt(i);
            //    resultG.Vertices[i] = v;
            //}


            //resultG.Edges = new GraphEdge[g.Edges.Count()];
            //for (int i = 0; i < g.Edges.Count(); i++)
            //{
            //    var e = g.Edges.ElementAt(i);
            //    resultG.Edges[i] = new GraphEdge(e.Source, e.Target);
            //}

            return resultG;
        }

        [OperationContract]
        public Graph ComputeCentralityFromGraphML(String MethodName, String graphML)
        {
            UndirectedGraph<SocialNetworkNode, EdgeWithAttributes.EdgeWithAttributes<SocialNetworkNode>> graph = GraphMLBuilder.Build<SocialNetworkNode>(graphML, HttpContext.Current.Server.MapPath("App_Data"));
            AdjacencyGraph<IGraphMLComplexType, EdgeWithAttributes.EdgeWithAttributes<IGraphMLComplexType>> network = new AdjacencyGraph<IGraphMLComplexType, EdgeWithAttributes.EdgeWithAttributes<IGraphMLComplexType>>();
            foreach (EdgeWithAttributes.EdgeWithAttributes<SocialNetworkNode> edge in graph.Edges)
            {
                EdgeWithAttributes.EdgeWithAttributes<IGraphMLComplexType> e = new EdgeWithAttributes.EdgeWithAttributes<IGraphMLComplexType>(edge.Source, edge.Target);
                network.AddVerticesAndEdge(e);
            }

            Type complex = typeof(ComplexNetCentralityLib.ComplexNetCentrality);
            complex.GetMethod(MethodName).Invoke(null, new object[] { network });

            var g = SocialNetworkNodeToGraphElement(graph);

            Graph resultG = new Graph() { ID = Guid.NewGuid() };
            resultG.Vertices = new List<GraphElement>();
            for (int i = 0; i < g.VertexCount; i++)
            {
                var v = g.Vertices.ElementAt(i);
                var elem = new GraphElement();
                elem.ID = Guid.NewGuid();
                elem.GraphID = resultG.ID;
                elem.Keys = new List<PairKeyValue>();
                elem.Keys = v.Keys;
                resultG.Vertices.Add(elem);
            }

            var list1 = new List<GraphEdge>();
            resultG.Edges = new List<GraphEdge>();
            for (int i = 0; i < g.Edges.Count(); i++)
            {
                var e = g.Edges.ElementAt(i);
                resultG.Edges.Add(new GraphEdge() { GraphID = resultG.ID, ID = Guid.NewGuid(), Source = e.Source.ID, Target = e.Target.ID, Condition = e.Condition });
            }

            return resultG;
        }

        private AdjacencyGraph<GraphElement, EdgeWithAttributes.EdgeWithAttributes<GraphElement>> SocialNetworkNodeToGraphElement(UndirectedGraph<SocialNetworkNode, EdgeWithAttributes.EdgeWithAttributes<SocialNetworkNode>> socialNetwork)
        {
            AdjacencyGraph<GraphElement, EdgeWithAttributes.EdgeWithAttributes<GraphElement>> resultGraph = new AdjacencyGraph<GraphElement, EdgeWithAttributes.EdgeWithAttributes<GraphElement>>();
            Dictionary<SocialNetworkNode, GraphElement> map = new Dictionary<SocialNetworkNode, GraphElement>();
            foreach (EdgeWithAttributes.EdgeWithAttributes<SocialNetworkNode> edge in socialNetwork.Edges)
            {

                GraphElement source = null;
                try
                {
                    source = map[edge.Source];
                }
                catch (KeyNotFoundException ex) { }

                GraphElement target = null;
                try
                {
                    target = map[edge.Target];
                }
                catch (KeyNotFoundException ex) { }

                if (source == null)
                {
                    source = new GraphElement();
                    source.ID = Guid.NewGuid();
                    map.Add(edge.Source, source);
                    source.x = edge.Source.x;
                    source.y = edge.Source.y;
                    source.Height = edge.Source.Height;
                    source.Width = edge.Source.Width;
                    //source.Id = source.GetHashCode();
                    for (int i = 0; i < edge.Source.Keys.Count; i++)
                    {

                        var k = edge.Source.Keys.ElementAt(i);
                        PairKeyValue v = new PairKeyValue();
                        //if (k.Key != "stateName")
                        //{
                        v.Key = k.Key;
                        v.Value = k.Value;
                        source.Keys.Add(v);
                        /*}
                        else
                        {
                            v.Key = k.Key;
                            v.Value = edge.Source.state.stateNode.stateName;
                            source.Keys.Add(v);
                        }*/

                    }
                    resultGraph.AddVertex(source);
                }

                if (target == null)
                {
                    target = new GraphElement();
                    target.ID = Guid.NewGuid();
                    map.Add(edge.Target, target);
                    target.x = edge.Target.x;
                    target.y = edge.Target.y;
                    target.Height = edge.Target.Height;
                    target.Width = edge.Target.Width;
                    for (int i = 0; i < edge.Target.Keys.Count; i++)
                    {
                        var k = edge.Target.Keys.ElementAt(i);
                        PairKeyValue v = new PairKeyValue();
                        //if (k.Key != "stateName")
                        //{
                        v.Key = k.Key;
                        v.Value = k.Value;
                        target.Keys.Add(v);
                        /*}
                        else
                        {
                            v.Key = k.Key;
                            v.Value = edge.Target.state.stateNode.stateName;
                            target.Keys.Add(v);
                        }*/
                    }
                    resultGraph.AddVertex(target);
                }

                EdgeWithAttributes.EdgeWithAttributes<GraphElement> e = new EdgeWithAttributes.EdgeWithAttributes<GraphElement>(source, target);
                resultGraph.AddEdge(e);
            }
            return resultGraph;
        }

        public int CountInfectious(Simulation s)
        {
            int count = 0;
            var v = s.getSimulationResult();

            foreach (var item in v.Vertices)
            {
                if (item.state.stateNode.stateName == "Infectious")
                {
                    count++;
                }
            }

            return count;
        }

        //[OperationContract]
        //public Graph GenerateGraph(string methodName, object[] parameters)
        //{
        //    MethodInfo method = typeof(ComplexNetGeneratorLib.ComplexNetGenerator).GetMethod(methodName);
        //    ComplexNetGenerator generator = new ComplexNetGenerator();

        //    ComplexNet net = method.Invoke(generator, parameters) as ComplexNet;

        //    Graph graph = CreateGraphFromComplexNet(net);

        //    DataBaseClassesDataContext db = new DataBaseClassesDataContext();
        //    var nodes = from n in db.Nodes
        //                select n;
        //    var nodesArray = nodes.ToArray();

        //    Random random = new Random();
        //    foreach (var vertex in graph.Vertices)
        //    {
        //        var n = nodesArray[random.Next() % nodesArray.Length];

        //        vertex.Keys.Add(new PairKeyValue("birthdate", n.birthdate.ToString()));
        //        vertex.Keys.Add(new PairKeyValue("country", n.country));
        //        vertex.Keys.Add(new PairKeyValue("image", n.image.ToString()));//zmiana spowodowana innym sposobem przechowywania zdjec
        //        vertex.Keys.Add(new PairKeyValue("latitude", n.latitude.ToString()));
        //        vertex.Keys.Add(new PairKeyValue("longitude", n.longitude.ToString()));
        //        vertex.Keys.Add(new PairKeyValue("name", n.name));
        //        vertex.Keys.Add(new PairKeyValue("postalcode", n.postalcode));
        //        vertex.Keys.Add(new PairKeyValue("street", n.street));
        //        vertex.Keys.Add(new PairKeyValue("surname", n.surname));
        //        vertex.Keys.Add(new PairKeyValue("town", n.town));
        //    }

        //    return graph;
        //}

        [OperationContract]
        public void changeNodeState(String token, Guid nodeId, String newStateName)
        {
            Simulation s = HttpContext.Current.Session["simulation"] as Simulation;
            if (s == null) return;

            s.changeNodeState(nodeId, newStateName);
        }

        [OperationContract]
        public void removeNode(String token, Guid nodeId)
        {
            Simulation s = HttpContext.Current.Session["simulation"] as Simulation;
            if (s == null) return;

            s.removeNode(nodeId);
        }

        [OperationContract]
        public void removeEdge(String token, Guid sourceId, Guid targetId)
        {
            Simulation s = HttpContext.Current.Session["simulation"] as Simulation;
            if (s == null) return;

            s.removeEdge(sourceId, targetId);
        }

        [OperationContract]
        public string[] GetAvailableStopConditions()
        {
            List<String> stopConditions = new List<string>();
            Type t = typeof(EpidemicSimulator.stopconditions.StopCondition);
            Assembly asm = t.Assembly;
            foreach (Type type in asm.GetTypes())
            {
                Type[] interfaces = type.GetInterfaces();
                foreach (Type interFace in interfaces)
                {

                    if (interFace.FullName == t.FullName)
                    {
                        String val = type.Name;
                        stopConditions.Add(val);
                    }
                }
            }
            return stopConditions.ToArray();
        }

        [OperationContract]
        public SimulationReport getSimulationReport(String token)
        {
            Simulation s = HttpContext.Current.Session["simulation"] as Simulation;
            if (s == null) return null;

            return s.getSimulationReport();
        }

        [OperationContract]
        public string netToGraphml(string netName)
        {
            db.DiseaseDataClassesDataContext db = new db.DiseaseDataClassesDataContext();
            if (db.DatabaseExists() == false) return null;
            var net = (from n in db.Nets where n.netName == netName select n).Single();

            string graphml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<graphml xmlns=\"http://graphml.graphdrawing.org/xmlns\" "
                + "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " + "xsi:schemaLocation=\"http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd\">\n";
            graphml += "\t<key id=\"id\" for=\"node\" attr.name=\"id\" attr.type=\"string\" />\n";
            graphml += "\t<key id=\"name\" for=\"node\" attr.name=\"name\" attr.type=\"string\" />\n";
            graphml += "\t<key id=\"surname\" for=\"node\" attr.name=\"surname\" attr.type=\"string\" />\n";
            graphml += "\t<key id=\"birthdate\" for=\"node\" attr.name=\"birthdate\" attr.type=\"string\" />\n";
            graphml += "\t<key id=\"photo\" for=\"node\" attr.name=\"photo\" attr.type=\"string\" />\n";
            graphml += "\t<key id=\"location\" for=\"node\" attr.name=\"location\" attr.type=\"string\" />\n";
            graphml += "\t<key id=\"locationX\" for=\"node\" attr.name=\"locationX\" attr.type=\"string\" />\n";
            graphml += "\t<key id=\"locationY\" for=\"node\" attr.name=\"locationY\" attr.type=\"string\" />\n";
            graphml += "\t<key id=\"street\" for=\"node\" attr.name=\"street\" attr.type=\"string\" />\n";
            graphml += "\t<key id=\"town\" for=\"node\" attr.name=\"town\" attr.type=\"string\" />\n";
            graphml += "\t<key id=\"postalcode\" for=\"node\" attr.name=\"postalcode\" attr.type=\"string\" />\n";
            graphml += "\t<key id=\"country\" for=\"node\" attr.name=\"country\" attr.type=\"string\" />\n";
            graphml += "\t<key id=\"stateName\" for=\"node\" attr.name=\"stateName\" attr.type=\"string\" />\n";
            graphml += "\t<graph edgedefault=\"undirected\">\n";

            var nodes = from n in db.Nodes select n;
            foreach (var n in nodes)
            {
                graphml += "\t\t<node id=\"node" + n.nodeID + "\">\n";
                graphml += "\t\t\t<data key=\"id\">n" + n.nodeID + "</data>\n";
                graphml += "\t\t\t<data key=\"name\">" + n.name + "</data>\n";
                graphml += "\t\t\t<data key=\"surname\">" + n.surname + "</data>\n";
                graphml += "\t\t\t<data key=\"birthdate\">" + n.birthdate + "</data>\n";
                graphml += "\t\t\t<data key=\"photo\">http://nosoifighters.studentlive.pl/GetImage.aspx?id=" + n.image + "</data>\n";
                graphml += "\t\t\t<data key=\"location\">" + n.country + "</data>\n";
                graphml += "\t\t\t<data key=\"locationX\">" + ((double)n.latitude).ToString(CultureInfo.CreateSpecificCulture("en-GB")) + "</data>\n";
                graphml += "\t\t\t<data key=\"locationY\">" + ((double)n.longitude).ToString(CultureInfo.CreateSpecificCulture("en-GB")) + "</data>\n";
                graphml += "\t\t\t<data key=\"street\">" + n.street + "</data>\n";
                graphml += "\t\t\t<data key=\"town\">" + n.town + "</data>\n";
                graphml += "\t\t\t<data key=\"postalcode\">" + n.postalcode + "</data>\n";
                graphml += "\t\t\t<data key=\"country\">" + n.country + "</data>\n";
                graphml += "\t\t\t<data key=\"stateName\">" + "Susceptible" + "</data>\n";
                graphml += "\t\t</node>\n";
            }

            var edges = (from e in db.Edges where e.netID == net.netID select e);
            foreach (var e in edges)
            {
                graphml += "\t\t<edge id=\"" + e.edgeID + "\" source=\"node" + e.leftNodeID + "\" target=\"node" + e.rightNodeID + "\" />\n";
            }

            graphml += "\t</graph>\n</graphml>\n";
            return graphml;
        }
    }
}
